//
// Created by bill3000 on 3/3/21.
//

#include "fruit.hpp"
#include "../log/logger.hpp"

int FruitFSM::algorithm_get_image_area(const cv::Mat &m) {
    cv::Mat ma[3];
    cv::cvtColor(m, m, cv::COLOR_BGR2HSV); //H: [0,180],S:[0,255],V:[0,255]
    cv::split(m, ma);
    cv::Scalar miu = cv::mean(ma[0]);
    cv::threshold(ma[0], ma[0], miu[0], 1, cv::THRESH_BINARY);
    cv::Scalar raw_area = cv::sum(ma[0]);

    return raw_area[0];
}

SizeModel FruitFSM::algorithm_sal_kmeans_learning(std::map<std::string, int> &cam_name_area_map, int k, const std::string& size) {
    cv::Mat kmeans_data(cam_name_area_map.size(), 1, CV_32FC1);
    cv::Mat centers(k, 1, CV_32FC1), labels;
    int r = 0;
    for(auto & iter : cam_name_area_map) {
        kmeans_data.at<float>(r++, 0) = iter.second;
    }
    cv::kmeans(kmeans_data, k, labels,
               cv::TermCriteria(cv::TermCriteria::EPS | cv::TermCriteria::COUNT, 10, 1.0),
               4, cv::KMEANS_RANDOM_CENTERS, centers);
    std::string sdir = "/intelli/working/";
    std::string ddir = "/intelli/tracking/size/";ddir.append(size);
    cv::sort(centers, centers, cv::SORT_EVERY_COLUMN);
    for(auto & iter : cam_name_area_map) {
        cv::Mat tc = centers.clone();
        std::string t;
        for (int i = 0; i < tc.rows; ++i) {
            tc.at<float>(i, 0) -= iter.second;
        }
        tc = cv::abs(tc);
        cv::Point loc;
        cv::minMaxLoc(tc, nullptr, nullptr, &loc, nullptr);
        loc.x == 0?t="large":(loc.x==1?"middle":(loc.x==2?"small":"large"));
        util_copy_file(sdir, iter.first, ddir + t);
    }

    SizeModel sm;
    sm.ls.camid = 0;
    sm.ls.small = (int)centers.at<float>(0, 0);
    sm.ls.middle = (int)centers.at<float>(1, 0);
    sm.ls.large = (int)centers.at<float>(2, 0);

    return sm;
}

int FruitFSM::algorithm_analysis_size_and_defect() {
    std::vector<std::string> fns;
    std::string sdir = "/intelli/tracking/size/";
    util_get_dir_content(sdir, fns);

    unsigned long mid = fns.size() / 2;
    std::string fn = fns.at(mid);
    fn = fn.substr(0, fn.find_last_of('-'));
    std::string fn1 = fn, fn2 = fn, fn3 = fn;
    fn1.append("-01.jpg"); fn2.append("-02.jpg"); fn3.append("-03.jpg");

    std::string ddir = "/intelli/working/";
    if ((util_copy_file(sdir, fn1, ddir) < 0) ||
        (util_copy_file(sdir, fn2, ddir) < 0) ||
        (util_copy_file(sdir, fn3, ddir) < 0)) {
        LOG(ERROR, "Copy file error, Can not sorting anymore !");
        sorting = false;
        pthread_exit(nullptr);
    }
    util_delete_dir_content("/intelli/tracking/size/");

    cv::Mat m1, m2, m3;
    m1 = cv::imread(ddir + fn1); m2 = cv::imread(ddir + fn2); m3 = cv::imread(ddir + fn2);
    if (m1.empty() || m2.empty() || m3.empty()) {
        LOG(ERROR, "Read image file error, Cannot sorting anymore !");
        sorting = false;
        pthread_exit(nullptr);
    }

    //Here, we should analyze defect
    //...If it is defect, return -1 directly.

    int area[3];
    area[0] = algorithm_get_image_area(m1);
    area[1] = algorithm_get_image_area(m2);
    area[2] = algorithm_get_image_area(m3);
    int small_count = 0, middle_count = 0, large_count = 0;
    for (int i = 0; i < 3; ++i) {
        int small_diff = abs(loaded_size_model[i].ls.small - area[i]);
        int middle_diff = abs(loaded_size_model[i].ls.middle - area[i]);
        int large_diff = abs(loaded_size_model[i].ls.large - area[i]);
        int min = util_get_min_from_multi_int(3, small_diff, middle_diff, large_diff);
        min==small_diff?small_count++:(min==middle_diff?middle_count++:large_count++);
    }
    int which = util_get_max_from_multi_int(3, small_count, middle_count, large_count);
    int size;
    which==small_count?size=3:(which==middle_count?size=2:size=1);
    return size;  //size,1:large, 2:middle, 3:large, -1:defect
}

int FruitFSM::algorithm_analysis_sugar() {
    std::vector<std::string> fns;
    std::string sdir = "/intelli/tracking/sugar/";
    util_get_dir_content(sdir, fns);

    unsigned long mid = fns.size() / 2;
    std::string fn = fns.at(mid);

    std::string ddir = "/intelli/working/";
    if (util_copy_file(sdir, fn, ddir) < 0) {
        LOG(ERROR, "Copy file error, Can not sorting anymore !");
        sorting = false;
        pthread_exit(nullptr);
    }
    util_delete_dir_content("/intelli/tracking/sugar/");

    cv::Mat m4;
    m4 = cv::imread(ddir + fn);
    if (m4.empty()) {
        LOG(ERROR, "Read image file error, Cannot sorting anymore !");
        sorting = false;
        pthread_exit(nullptr);
    }

    //Here, we should analyze sugar by the image of m4
    //and return the value
    //1:sweat, 2: not sweat

    return 1;
}


